package com.hexun.dubbo.counter;

import com.netflix.hystrix.util.HystrixRollingNumber;
import com.netflix.hystrix.util.HystrixRollingNumberEvent;
import org.apache.commons.collections.map.LRUMap;

/**
 * 滑窗计数器
 */
public class RollingCounterPool {

    /**
     * key map
     */
    private LRUMap map;

    /**
     * 窗体时间段
     */
    private int timeInMilliseconds;

    /**
     * 滑窗计数 bucket 数量
     */
    private int numberOfBuckets;

    /**
     * 创建一个计数器池
     *
     * @param maxSize            lrumap max size
     * @param timeInMilliseconds 窗体时间段
     * @param numberOfBuckets    滑窗计数 bucket 数量
     */
    public RollingCounterPool(int maxSize, int timeInMilliseconds, int numberOfBuckets) {
        map = new LRUMap(maxSize);
        this.timeInMilliseconds = timeInMilliseconds;
        this.numberOfBuckets = numberOfBuckets;
    }

    private HystrixRollingNumberEvent EVENT = HystrixRollingNumberEvent.SUCCESS;

    /**
     * 记录一条数据,计数加一
     *
     * @param key
     */
    public void record(String key) {
        Object o = map.get(key);
        if (o != null) {
            HystrixRollingNumber number = (HystrixRollingNumber) o;
            number.increment(EVENT);
        } else {
            HystrixRollingNumber number = new HystrixRollingNumber(timeInMilliseconds, numberOfBuckets);
            map.put(key, number);
        }
    }

    /**
     * 判断滑窗计数是否大于{value}
     *
     * @param value 阈值
     * @return 结果
     */
    public boolean gt(String key, int value) {
        Object o = map.get(key);
        if (o != null) {
            HystrixRollingNumber number = (HystrixRollingNumber) o;
            return number.getRollingSum(EVENT) > value;
        }
        return false;
    }
}
